#pragma once
#include <queue>
#include <memory>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/socket.h>
#include <unistd.h>
#include <atomic>
#include <cstring>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
#include <atomic>
#include <string>
#include <unordered_map>
#include "LogicSystem.h"
#include "global.h"


class IOTask{
public:
    IOTask(int fd, TaskType type, std::string data="", int msgtype=0):_fd(fd),
    _type(type),_data(data),_msgtype(msgtype){}
    ~IOTask() = default;
    TaskType _type;
    int _fd;
    std::string _data;
    int _msgtype;
};

class NoneCopy{
protected:
   NoneCopy() = default;
private:
    NoneCopy(const NoneCopy & cp) = delete;
    NoneCopy & operator = (const NoneCopy& ) = delete; 
};
class Session;
class IOThread : public NoneCopy, public std::enable_shared_from_this<IOThread> {
public:
    IOThread(int index);
    ~IOThread();
    void start();
    void stop();
    void join();
    bool add_fd(int fd, int events);
    bool mod_fd(int fd, int events);
    bool del_fd(int fd);
    void wakeup();
    int set_nonblocking(int fd);
    void enqueue_new_con(int fd);// 入队新连接
    void catche_new_con(int fd);
    void enqueue_task(std::shared_ptr<IOTask> task);// 入队任务
    void enqueue_send_data(int fd, const std::string& msg, int msgtype);// 入队发送数据任务 
    void handle_epollout(std::shared_ptr<Session> sess);
    size_t get_conn_num() const { return _sessions.size(); }
    void check_timeouts();  // 检测超时

private:
    
    bool deal_enque_tasks(); // 处理入队任务
    void clear_fd(int fd);// 清理文件描述符
    void loop(); // 事件循环

    
    int _event_fd;
    int _epoll_fd;
    std::mutex _task_mtx;
    std::queue<std::shared_ptr<IOTask>> _tasks;
    //struct epoll_event* _event_addr;
    std::vector<struct epoll_event> _event_addr;
    int _event_count;
    std::thread _thread;
    std::atomic<bool> _stop;
    int _index;
    std::unordered_map<int, std::shared_ptr<Session>> _sessions;
    bool _expanded_once;

    LogicSystem* _logic_system;
};

// int read_head_data(std::shared_ptr<Session> sess);
// int read_body_data(std::shared_ptr<Session> sess);